//备注：拷贝代码请加上作者信息
//作者：王海涛
//邮箱：1126471088@qq.com
//版本：V0.1.2
#include "74hc595_driver.h"
#include <string.h>


static volatile unsigned int* SCL;
static volatile unsigned int* SDA;
static volatile unsigned int* LOCK;

static unsigned char HC595_Channel_Data[HC595_MAX_CH_COUNT];


static void WHT_HC595_Driver_GPIO_Init(void)
{
    WHT_GPIO_BSP.WHT_Set_Clock(HC595_SCL_Port, ENABLE);
    WHT_GPIO_BSP.WHT_Set_Clock(HC595_SDA_Port, ENABLE);
    WHT_GPIO_BSP.WHT_Set_Clock(HC595_LOCK_Port, ENABLE);

    WHT_GPIO_BSP.WHT_Set_Pin(HC595_SCL_Port, HC595_SCL_Pin, Hig);
    WHT_GPIO_BSP.WHT_Set_Pin(HC595_SDA_Port, HC595_SDA_Pin, Hig);
    WHT_GPIO_BSP.WHT_Set_Pin(HC595_LOCK_Port, HC595_LOCK_Pin, Hig);

    WHT_GPIO_BSP.WHT_Register_Bit_Output(HC595_SCL_Port, HC595_SCL_Pin, &SCL);
    WHT_GPIO_BSP.WHT_Register_Bit_Output(HC595_SDA_Port, HC595_SDA_Pin, &SDA);
    WHT_GPIO_BSP.WHT_Register_Bit_Output(HC595_LOCK_Port, HC595_LOCK_Pin, &LOCK);

    WHT_GPIO_BSP.WHT_Set_Mode(HC595_SCL_Port, HC595_SCL_Pin, Mode_Out_PP);
    WHT_GPIO_BSP.WHT_Set_Mode(HC595_SDA_Port, HC595_SDA_Pin, Mode_Out_PP);
    WHT_GPIO_BSP.WHT_Set_Mode(HC595_LOCK_Port, HC595_LOCK_Pin, Mode_Out_PP);
}
static void WHT_HC595_Driver_Speed(void)
{
    /*此处为空速度能达到2Mhz*/
    WHT_Delay_us(HC595_DELAY_TIME);
}

static void WHT_HC595_Driver_F5_All_Channel_Status(void)
{
    unsigned short Count = HC595_COUNT;

    *LOCK = Low;
    while (Count--)
    {
        for (unsigned char i = 0x80; i != 0x00; i >>=1)
        {
            *SCL = Low;
            *SDA = HC595_Channel_Data[Count] & i ? Hig : Low;
            WHT_HC595_Driver_Speed();
            *SCL = Hig;
            WHT_HC595_Driver_Speed();
        }
    }
    *SDA = Hig;
    *LOCK = Hig;
}
static void WHT_HC595_Driver_Set_Channel_Status(unsigned short ch, ControlStatus status)
{
    if (ch >= sizeof(HC595_Channel_Data))
        return;

    if (status == ENABLE)
        HC595_Channel_Data[ch >> 3] |= 0x01 << (ch & 0x07);
    else
        HC595_Channel_Data[ch >> 3] &= ~(0x01 << (ch & 0x07));
}
static void WHT_HC595_Driver_Set_All_Channel_Status(ControlStatus status)
{
    memset(HC595_Channel_Data, status == ENABLE ? 0xff : 0x00, sizeof(HC595_Channel_Data));
    WHT_HC595_Driver_F5_All_Channel_Status();
}
static void WHT_HC595_Init(void)
{
    WHT_HC595_Driver_GPIO_Init();
    WHT_HC595_Driver_Set_All_Channel_Status(DISABLE);
}

const WHT_HC595_Driver_t WHT_HC595_Driver =
{
    .WHT_Init                   = WHT_HC595_Init,
    .WHT_F5_All_Channel_Status  = WHT_HC595_Driver_F5_All_Channel_Status,
    .WHT_Set_All_Channel_Status = WHT_HC595_Driver_Set_All_Channel_Status,
    .WHT_Set_Channel_Status     = WHT_HC595_Driver_Set_Channel_Status,
};
